#!/bin/csh -f

####################################################################################
## Copyright (c) 2014, University of British Columbia (UBC)  All rights reserved. ##
##                                                                                ##
## Redistribution  and  use  in  source   and  binary  forms,   with  or  without ##
## modification,  are permitted  provided that  the following conditions are met: ##
##   * Redistributions   of  source   code  must  retain   the   above  copyright ##
##     notice,  this   list   of   conditions   and   the  following  disclaimer. ##
##   * Redistributions  in  binary  form  must  reproduce  the  above   copyright ##
##     notice, this  list  of  conditions  and the  following  disclaimer in  the ##
##     documentation and/or  other  materials  provided  with  the  distribution. ##
##   * Neither the name of the University of British Columbia (UBC) nor the names ##
##     of   its   contributors  may  be  used  to  endorse  or   promote products ##
##     derived from  this  software without  specific  prior  written permission. ##
##                                                                                ##
## THIS  SOFTWARE IS  PROVIDED  BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ##
## AND  ANY EXPRESS  OR IMPLIED WARRANTIES,  INCLUDING,  BUT NOT LIMITED TO,  THE ##
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ##
## DISCLAIMED.  IN NO  EVENT SHALL University of British Columbia (UBC) BE LIABLE ##
## FOR ANY DIRECT,  INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL ##
## DAMAGES  (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF  SUBSTITUTE GOODS OR ##
## SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) HOWEVER ##
## CAUSED AND ON ANY THEORY OF LIABILITY,  WHETHER IN CONTRACT, STRICT LIABILITY, ##
## OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ##
## OF  THIS SOFTWARE,  EVEN  IF  ADVISED  OF  THE  POSSIBILITY  OF  SUCH  DAMAGE. ##
####################################################################################

####################################################################################
##                     Run-in-batch Simulation  Flow Manager                      ##
##                                                                                ##
##    Author: Ameer M. Abdelhadi (ameer@ece.ubc.ca, ameer.abdelhadi@gmail.com)    ##
## Switchable SRAM-based Multi-ported RAMs; University of British Columbia, 2014  ##
####################################################################################

####################################################################################
## USAGE:                                                                         ##
##   ./sim <Depth List> <Width List> <#Write Ports List (Normal-Extended)> \      ##
##         <#Read Ports List (Normal-Extended)> <Bypass List> <#Cycles> [verbose] ##
##                                                                                ##
## - Use a comma delimited list.                                                  ##
##   - No spaces.                                                                 ##
##   - May be surrounded by any brackets (), [], {}, or <>.                       ##
## - RAM depth, data width, and simulation cycles are positive integers.          ##
## - Numbers of read and write ports are pairs of normal-extended port numbers    ##
##   delimited with hyphen "-".                                                   ##
##   - numbers of normal read/write ports are positive integers.                  ##
##   - 0                   <= # Extended write ports <=     # normal write ports  ##
##   - # normal read ports <= # Extended read  ports <= 2 * # noraml read  ports  ##
## - "verbose" is an optional argument; use if verbosed logging is required       ##
##                                                                                ##
## EXAMPLES:                                                                      ##
## ./sim 1024 32 3-2 2-4 1000000 verbose                                          ##
##    Simulate 1M cycles of a 1K lines RAM, 32 bits width, 3 normal / 2 extended  ##
##    write & 2 normal / 4 extended read ports, verbose logging,                  ##
## ./sim 512,1024 8,16,32 2,3,4 1,2,3,4 1000000                                   ##
##    Simulate 1M cycles of RAMs with 512 or 1024 lines, 8, 16, or 32 bits width, ##
##    2,3, or 4 write ports, 1,2,3, or 4 read ports. Total of 72 combinations.    ##
##                                                                                ##
## The following files and directories will be created after simulation :         ##
##   - sim.res : A list of simulation results, each run in a separate line,       ##
##               including all design styles.                                     ##
####################################################################################

# setup environment variables and Altera's CAD tools 
# change file to your own flow if necessary 
source ./altera.12.0.csh

# create work if not exist
if !(-d work) vlib work

# require exactly 6 arguments
if ( (${#argv} != 6) & (${#argv} != 7) ) then
    printf '\x1b[%i;3%im' 1 1
    printf 'Error: Exactly 6 or 7 arguments are required\n'
    printf '\x1b[0m'
    goto errorMessage
endif

# convert each argument list into a c-shell list (romove commas and etc.)

set RDLST = (`echo ${argv[1]} | tr ",()[]{}<>" " "`)
set DWLST = (`echo ${argv[2]} | tr ",()[]{}<>" " "`)
set NWLST = (`echo ${argv[3]} | tr ",()[]{}<>" " "`)
set NRLST = (`echo ${argv[4]} | tr ",()[]{}<>" " "`)
set BYLST = (`echo ${argv[5]} | tr ",()[]{}<>" " "`)
set CYCC  = ${argv[6]}

# check if verbose is required
set VERB = 0
if ( ${#argv} == 7 ) then
  if ( (${argv[7]} == "verbose") | (${argv[7]} == "verb") | (${argv[7]} == "v")) then
    set VERB = 1
  else
    printf '\x1b[%i;3%im' 1 1
    printf "Error: Check arguments syntax\n"
    printf '\x1b[0m'
    goto errorMessage
  endif
endif

# check arguments correctness (positive integer numbers)
foreach ARGVAL ($RDLST $DWLST $CYCC)
  set ARGVALIsNumber=`echo $ARGVAL | egrep -c '^[0-9]+$'`
  if ($ARGVALIsNumber != 1) then
    printf '\x1b[%i;3%im' 1 1
    printf "Error (${ARGVAL}): Depth, width, numner of read/write ports arguments should be possitive integer numbers\n"
    printf '\x1b[0m'
    goto errorMessage
  endif
end

# check arguments correctness (positive integer numbers)
foreach ARGVAL ($NWLST $NRLST)
  set ARGVALIsNumber_=`echo $ARGVAL | egrep -c '^[0-9]+(\-[0-9])?[0-9]*$'`
  if ($ARGVALIsNumber_ != 1) then
    printf '\x1b[%i;3%im' 1 1
    echo 'Error: The number of reading and writing ports should be possitive integer numbers'
    echo '       Use "-" to seperate normal from extended mode parameters'
    goto errorMessage
  endif
end

# check bypass list argument correctness
foreach BYVAL ($BYLST)
  if ( ($BYVAL != "NON") & ($BYVAL != "WAW") & ($BYVAL != "RAW") & ($BYVAL != "RDW") ) then
    printf '\x1b[%i;3%im' 1 1
    printf "Error (${BYVAL}): Bypass list should be a list of NON, WAW, RAW, or RDW\b\n"
    printf '\x1b[0m'
    goto errorMessage
  endif
end

# total different fifo designs
@ FlowOprNum = ((${#RDLST})*(${#DWLST})*(${#NWLST})*(${#NRLST})*(${#BYLST}))
@ FlowOprCnt = 0

printf '\x1b[%i;3%im' 7 4
printf "= Simulate in batch with the following parameters:\n"
printf "= RAM Depth         : $RDLST\n"
printf "= Data Width        : $DWLST\n"
printf "= Write Ports       : $NWLST\n"
printf "= Read  Ports       : $NRLST\n"
printf "= Simulation Cycles : $CYCC\n"
printf "= Bypass            : $BYLST\n"
printf '\x1b[0m'

# operate on all different RAM parameters
  foreach CURRD ($RDLST)
    foreach CURDW ($DWLST)
      foreach CURNW_ ($NWLST)
        # extract normal and extended parameters
        set CURNW  = `echo $CURNW_|cut -d"-" -f1`
        set CURNWE = `echo $CURNW_|cut -d"-" -f2`
        if (CURNWE == "") set CURNWE = $CURNW
        foreach CURNR_ ($NRLST)
        # extract normal and extended parameters
          set CURNR  = `echo $CURNR_|cut -d"-" -f1`
          set CURNRE = `echo $CURNR_|cut -d"-" -f2`
          if (CURNRE == "") set CURNRE = $CURNR
          foreach CURBY ($BYLST)
            @ FlowOprCnt++

            printf '\x1b[%i;3%im' 7 2
            printf "\n== Starting Simulation (${FlowOprCnt}/${FlowOprNum}): [Depth:${CURRD}; Width:${CURDW}; Writes:${CURNW}; Reads:${CURNR}; Bypass:${CURBY}; Cycles:${CYCC}]\n"
            printf '\x1b[0m'

            # run current simulation
            vlog -work work +define+MEMD=$CURRD+DATW=$CURDW+nWPN=$CURNW+nRPN=$CURNR+nWPE=$CURNWE+nRPE=$CURNRE+BYPS=\"${CURBY}\"+VERB=$VERB+CYCC=$CYCC dpram.v lvt_bin.v mpram_lvt.v mpram_reg.v smpram.v mpram_xor.v utils.vh lvt_1ht.v lvt_reg.v smpram_tb.v mrram.v mrram_ext.v dpram_bbs.v
            vsim -c -L altera_mf_ver -L lpm_ver -do "run -all" smpram_tb

            printf '\x1b[%i;3%im' 7 2
            printf "== Simulation (${FlowOprCnt}/${FlowOprNum}) Completed: [Depth:${CURRD}; Width:${CURDW}; Writes:${CURNW}; Reads:${CURNR}; Bypass:${CURBY}; Cycles:${CYCC}]\n"
            printf '\x1b[0m'

      end
    end
  end
end

# clean unrequired files / after run
 foreach fileName (*.mif *.hex *.ver *.wlf *.vstf *.log transcript work)
   \rm -rf $fileName
 end


goto scriptEnd

# error message
errorMessage:
printf '\x1b[%i;3%im' 1 1
printf 'USAGE:                                                                        \n'
printf '  ./sim <Depth List> <Width List> <#Write Ports List (Normal-Extended)> \\    \n'
printf '        <#Read Ports List (Normal-Extended)> <Bypass List> <#Cycles> [verbose]\n'
printf '- Use a comma delimited list.                                                 \n'
printf '  - No spaces.                                                                \n'
printf '  - May be surrounded by any brackets (), [], {}, or <>.                      \n'
printf '- RAM depth, data width, and simulation cycles are positive integers.         \n'
printf '- Numbers of read and write ports are pairs of normal-extended port numbers   \n'
printf '  delimited with hyphen "-".                                                  \n'
printf '  - numbers of normal read/write ports are positive integers.                 \n'
printf '  - 0                   <= # Extended write ports <=     # normal write ports \n'
printf '  - # normal read ports <= # Extended read  ports <= 2 * # noraml read  ports \n'
printf '- "verbose" is an optional argument; use if verbosed logging is required      \n'
printf 'EXAMPLES:                                                                     \n'
printf './sim 1024 32 3-2 2-4 1000000 verbose                                         \n'
printf '   Simulate 1M cycles of a 1K lines RAM, 32 bits width, 3 normal / 2 extended \n'
printf '   write & 2 normal / 4 extended read ports, verbose logging,                 \n'
printf './sim 512,1024 8,16,32 2,3,4 1,2,3,4 1000000                                  \n'
printf '   Simulate 1M cycles of RAMs with 512 or 1024 lines, 8, 16, or 32 bits width,\n'
printf '   2,3, or 4 write ports, 1,2,3, or 4 read ports. Total of 72 combinations.   \n'
printf 'The following files and directories will be created after simulation :        \n'
printf '  - sim.res : A list of simulation results, each run in a separate line,      \n'
printf '              including all design styles.                                    \n'
printf '\x1b[0m'

scriptEnd:

